/*
	This file is part of Vajolet.

    Vajolet is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    Vajolet is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with Vajolet.  If not, see <http://www.gnu.org/licenses/>
*/

#include "vajolet.h"
#include <iostream>
#include <algorithm>
#include <cmath>
#include "bitops.h"
#include "movegen.h"

int BOARDINDEX[8][8];
bitMap BITSET[64];
// used in Eugene Nalimov's bitScanReverse
int MS1BTABLE[256];

bitMap RANKMASK[64];
bitMap FILEMASK[64];
bitMap KINGRAYS[64];

bitMap DIAGA1H8MASK[64];
bitMap DIAGA8H1MASK[64];

bitMap MASKBD[2];
bitMap MASKCE[2];
bitMap MASKFG[2];
bitMap MASKEG[2];

bitMap ISOLATED_PAWN[64];
bitMap PASSED_PAWN[2][64];
bitMap SQUARES_IN_FRONT_OF[2][64];
bitMap KINGSHIELD[2][64];
bitMap PAWNKINGSHIELD[2][2][64];



extern const int A8 = 56; extern const int B8 = 57; extern const int C8 = 58; extern const int D8 = 59;
extern const int E8 = 60; extern const int F8 = 61; extern const int G8 = 62; extern const int H8 = 63;
extern const int A7 = 48; extern const int B7 = 49; extern const int C7 = 50; extern const int D7 = 51;
extern const int E7 = 52; extern const int F7 = 53; extern const int G7 = 54; extern const int H7 = 55;
extern const int A6 = 40; extern const int B6 = 41; extern const int C6 = 42; extern const int D6 = 43;
extern const int E6 = 44; extern const int F6 = 45; extern const int G6 = 46; extern const int H6 = 47;
extern const int A5 = 32; extern const int B5 = 33; extern const int C5 = 34; extern const int D5 = 35;
extern const int E5 = 36; extern const int F5 = 37; extern const int G5 = 38; extern const int H5 = 39;
extern const int A4 = 24; extern const int B4 = 25; extern const int C4 = 26; extern const int D4 = 27;
extern const int E4 = 28; extern const int F4 = 29; extern const int G4 = 30; extern const int H4 = 31;
extern const int A3 = 16; extern const int B3 = 17; extern const int C3 = 18; extern const int D3 = 19;
extern const int E3 = 20; extern const int F3 = 21; extern const int G3 = 22; extern const int H3 = 23;
extern const int A2 =  8; extern const int B2 =  9; extern const int C2 = 10; extern const int D2 = 11;
extern const int E2 = 12; extern const int F2 = 13; extern const int G2 = 14; extern const int H2 = 15;
extern const int A1 =  0; extern const int B1 =  1; extern const int C1 =  2; extern const int D1 =  3;
extern const int E1 =  4; extern const int F1 =  5; extern const int G1 =  6; extern const int H1 =  7;

int whiteIndex[64] = {
A8, B8, C8, D8, E8, F8, G8, H8,
A7, B7, C7, D7, E7, F7, G7, H7,
A6, B6, C6, D6, E6, F6, G6, H6,
A5, B5, C5, D5, E5, F5, G5, H5,
A4, B4, C4, D4, E4, F4, G4, H4,
A3, B3, C3, D3, E3, F3, G3, H3,
A2, B2, C2, D2, E2, F2, G2, H2,
A1, B1, C1, D1, E1, F1, G1, H1
};
 
int blackIndex[64] = {
A1, B1, C1, D1, E1, F1, G1, H1,
A2, B2, C2, D2, E2, F2, G2, H2,
A3, B3, C3, D3, E3, F3, G3, H3,
A4, B4, C4, D4, E4, F4, G4, H4,
A5, B5, C5, D5, E5, F5, G5, H5,
A6, B6, C6, D6, E6, F6, G6, H6,
A7, B7, C7, D7, E7, F7, G7, H7,
A8, B8, C8, D8, E8, F8, G8, H8
};

extern const int FILES[64] = {
	0, 1, 2, 3, 4, 5, 6, 7,
	0, 1, 2, 3, 4, 5, 6, 7,
	0, 1, 2, 3, 4, 5, 6, 7,
	0, 1, 2, 3, 4, 5, 6, 7,
	0, 1, 2, 3, 4, 5, 6, 7,
	0, 1, 2, 3, 4, 5, 6, 7,
	0, 1, 2, 3, 4, 5, 6, 7,
	0, 1, 2, 3, 4, 5, 6, 7,
};
 
extern const int RANKS[64] = {
	0, 0, 0, 0, 0, 0, 0, 0,
	1, 1, 1, 1, 1, 1, 1, 1,
	2, 2, 2, 2, 2, 2, 2, 2,
	3, 3, 3, 3, 3, 3, 3, 3,
	4, 4, 4, 4, 4, 4, 4, 4,
	5, 5, 5, 5, 5, 5, 5, 5,
	6, 6, 6, 6, 6, 6, 6, 6,
	7, 7, 7, 7, 7, 7, 7, 7,
};

extern const int SQUARE_COLOR[64]={
		0,1,0,1,0,1,0,1,
		1,0,1,0,1,0,1,0,
		0,1,0,1,0,1,0,1,
		1,0,1,0,1,0,1,0,
		0,1,0,1,0,1,0,1,
		1,0,1,0,1,0,1,0,
		0,1,0,1,0,1,0,1,
		1,0,1,0,1,0,1,0
};

bitMap SQUARE_COLOR_BITMAP[2];

int squareDistance[64][64];

// Move generator shift for ranks:
extern const int RANKSHIFT[64] = {
        1,  1,  1,  1,  1,  1,  1,  1,
        9,  9,  9,  9,  9,  9,  9,  9,
       17, 17, 17, 17, 17, 17, 17, 17,  
       25, 25, 25, 25, 25, 25, 25, 25,
       33, 33, 33, 33, 33, 33, 33, 33,
       41, 41, 41, 41, 41, 41, 41, 41,
       49, 49, 49, 49, 49, 49, 49, 49,
       57, 57, 57, 57, 57, 57, 57, 57
};
 
// Move generator magic multiplication numbers for files:
extern const bitMap _FILEMAGICS[8] = {
       0x8040201008040200,
       0x4020100804020100,
       0x2010080402010080,
       0x1008040201008040,
       0x0804020100804020,
       0x0402010080402010,
       0x0201008040201008,
       0x0100804020100804
};
 
// Move generator magic multiplication numbers for diagonals:
extern const bitMap _MG_DIAGA8H1MAGICS[15] = {
       0x0,
       0x0,
       0x0101010101010100,
       0x0101010101010100,
       0x0101010101010100,
       0x0101010101010100,
       0x0101010101010100,
       0x0101010101010100,
       0x0080808080808080,
       0x0040404040404040,
       0x0020202020202020,
       0x0010101010101010,
       0x0008080808080808,
       0x0,
       0x0
};
 
// Move generator magic multiplication numbers for diagonals:
extern const bitMap _MG_DIAGA1H8MAGICS[15] = {
       0x0,
       0x0,
       0x0101010101010100,
       0x0101010101010100,
       0x0101010101010100,
       0x0101010101010100,
       0x0101010101010100,
       0x0101010101010100,
       0x8080808080808000,
       0x4040404040400000,
       0x2020202020000000,
       0x1010101000000000,
       0x0808080000000000,
       0x0,
       0x0
};
 

// Move generator 6-bit masking and magic multiplication numbers:
bitMap MG_RANKMASK[64];
bitMap MG_FILEMASK[64];
bitMap MG_FILEMAGIC[64];
bitMap MG_DIAGA8H1MASK[64];
bitMap MG_DIAGA8H1MAGIC[64];
bitMap MG_DIAGA1H8MASK[64];
bitMap MG_DIAGA1H8MAGIC[64];

unsigned char GEN_SLIDING_ATTACKS[8][64];
bitMap WHITE_PAWN_ATTACKS[64];
bitMap WHITE_PAWN_MOVES[64];
bitMap WHITE_PAWN_DOUBLE_MOVES[64];
bitMap BLACK_PAWN_ATTACKS[64];
bitMap BLACK_PAWN_MOVES[64];
bitMap BLACK_PAWN_DOUBLE_MOVES[64];
bitMap KNIGHT_ATTACKS[64];
bitMap KING_ATTACKS[64];
bitMap RANK_ATTACKS[64][64];      // 32KB
bitMap FILE_ATTACKS[64][64];      // 32KB
bitMap DIAGA8H1_ATTACKS[64][64];  // 32KB
bitMap DIAGA1H8_ATTACKS[64][64];  // 32KB
bitMap SQUARES_BETWEEN[64][64];
bitMap* SQUARES_BETWEEN_DIRECTION[64][64];


void dataInit(void){
	unsigned char CHARBITSET[8];
	int i, square, rank, file, arank, afile, state, slide, diaga1h8, diaga8h1, attackbit;
    unsigned char state6Bit, state8Bit, attack8Bit;

	//===========================================================================
	//     BITSET has only one bit set:
	//===========================================================================
	BITSET[0] = 0x1;
	for (i = 1; i < 64 ; i++)
	{
		BITSET[i] = BITSET[i-1] << 1;
	}
	//===========================================================================
	//BOARDINDEX is used to translate [file][rank] to [square],
	//===========================================================================

	for (rank = 0 ; rank < 8; rank++)
	{
		for (file = 0 ; file < 8; file++)
		{
			BOARDINDEX[file][rank] = (rank) * 8 + file;
		}
	}
	//===========================================================================
	//Initialize MS1BTABLE, used in lastOne (see bitops.cpp)
	//===========================================================================
    for (i = 0; i < 256; i++)
    {
		MS1BTABLE[i] = (
			(i > 127) ? 7 :
			(i >  63) ? 6 :
			(i >  31) ? 5 :
			(i >  15) ? 4 :
			(i >   7) ? 3 :
			(i >   3) ? 2 :
			(i >   1) ? 1 : 0 );
	}
	
	//===========================================================================
	//Initialize rank, file and diagonal 6-bit masking bitmaps, to get the
	//occupancy state, used in the movegenerator (see movegen.ccp)
	//===========================================================================
	
	for (square = 0; square < 64; square++)
	{
		MG_RANKMASK[square] = 0x0;
		MG_FILEMASK[square] = 0x0;
		MG_DIAGA8H1MASK[square] = 0x0;
		MG_DIAGA1H8MASK[square] = 0x0;
		MG_FILEMAGIC[square] = 0x0;
		MG_DIAGA8H1MAGIC[square] = 0x0;
		MG_DIAGA1H8MAGIC[square] = 0x0;
	}
	
	for (file = 0; file < 8; file++)
	{
		for (rank = 0; rank < 8; rank++)
		{
			//===========================================================================
			//initialize 6-bit rank mask, used in the movegenerator (see movegen.ccp)
			//===========================================================================
			
			MG_RANKMASK[BOARDINDEX[file][rank]]  = BITSET[BOARDINDEX[1][rank]] | BITSET[BOARDINDEX[2][rank]] | BITSET[BOARDINDEX[3][rank]] ;
			MG_RANKMASK[BOARDINDEX[file][rank]] |= BITSET[BOARDINDEX[4][rank]] | BITSET[BOARDINDEX[5][rank]] | BITSET[BOARDINDEX[6][rank]] ;
			
			//===========================================================================
			//initialize 6-bit file mask, used in the movegenerator (see movegen.ccp)
			//===========================================================================
			MG_FILEMASK[BOARDINDEX[file][rank]]  = BITSET[BOARDINDEX[file][1]] | BITSET[BOARDINDEX[file][2]] | BITSET[BOARDINDEX[file][3]] ;
			MG_FILEMASK[BOARDINDEX[file][rank]] |= BITSET[BOARDINDEX[file][4]] | BITSET[BOARDINDEX[file][5]] | BITSET[BOARDINDEX[file][6]] ;

			//===========================================================================
			//Initialize diagonal magic multiplication numbers, used in the movegenerator (see movegen.ccp)
			//===========================================================================
			diaga8h1 = file + rank; // from 0 to 14, longest diagonal = 7
			MG_DIAGA8H1MAGIC[BOARDINDEX[file][rank]] = _MG_DIAGA8H1MAGICS[diaga8h1];

			
			//===========================================================================
			//Initialize 6-bit diagonal mask, used in the movegenerator (see movegen.ccp)
			//===========================================================================
			MG_DIAGA8H1MASK[BOARDINDEX[file][rank]] = 0x0;
			if (diaga8h1 < 8)  // lower half, diagonals 0 to 7
			{
				for (square = 1 ; square < diaga8h1 ; square ++)
				{
					MG_DIAGA8H1MASK[BOARDINDEX[file][rank]] |= BITSET[BOARDINDEX[square][diaga8h1-square]];
				}
			}
			else  // upper half, diagonals 8 to 14
			{
				for (square = 1 ; square < 14 - diaga8h1 ; square ++)
				{
					MG_DIAGA8H1MASK[BOARDINDEX[file][rank]] |= BITSET[BOARDINDEX[diaga8h1+square-7][7-square]];
				}
			}

			
			//===========================================================================
			//Initialize diagonal magic multiplication numbers, used in the movegenerator (see movegen.ccp)
			//===========================================================================
			diaga1h8 = file - rank; // from -7 to +7, longest diagonal = 0
			MG_DIAGA1H8MAGIC[BOARDINDEX[file][rank]] = _MG_DIAGA1H8MAGICS[diaga1h8+7];
 
			//===========================================================================
			//Initialize 6-bit diagonal mask, used in the movegenerator (see movegen.ccp)
			//===========================================================================
			MG_DIAGA1H8MASK[BOARDINDEX[file][rank]] = 0x0;
			if (diaga1h8 > -1)  // lower half, diagonals 0 to 7
			{
				for (square = 1 ; square < 7 - diaga1h8 ; square ++)
				{
					MG_DIAGA1H8MASK[BOARDINDEX[file][rank]] |= BITSET[BOARDINDEX[diaga1h8 + square][square]];
				}
			}
			else
			{
				for (square = 1 ; square < 7 + diaga1h8 ; square ++)
				{
					MG_DIAGA1H8MASK[BOARDINDEX[file][rank]] |= BITSET[BOARDINDEX[square][square - diaga1h8]];
				}
			}
			
			//===========================================================================
			//Initialize file magic multiplication numbers, used in the movegenerator (see movegen.ccp)
			//===========================================================================
			MG_FILEMAGIC[BOARDINDEX[file][rank]] = _FILEMAGICS[file];

			
			//===========================================================================
			//initialize 8-bit rank mask
			//===========================================================================
			
			RANKMASK[BOARDINDEX[file][rank]]  = BITSET[BOARDINDEX[0][rank]] | BITSET[BOARDINDEX[1][rank]] | BITSET[BOARDINDEX[2][rank]] | BITSET[BOARDINDEX[3][rank]] ;
			RANKMASK[BOARDINDEX[file][rank]] |= BITSET[BOARDINDEX[4][rank]] | BITSET[BOARDINDEX[5][rank]] | BITSET[BOARDINDEX[6][rank]] | BITSET[BOARDINDEX[7][rank]] ;
			
			//===========================================================================
			//initialize 8-bit file mask
			//===========================================================================
			FILEMASK[BOARDINDEX[file][rank]]  = BITSET[BOARDINDEX[file][0]] | BITSET[BOARDINDEX[file][1]] | BITSET[BOARDINDEX[file][2]] | BITSET[BOARDINDEX[file][3]] ;
			FILEMASK[BOARDINDEX[file][rank]] |= BITSET[BOARDINDEX[file][4]] | BITSET[BOARDINDEX[file][5]] | BITSET[BOARDINDEX[file][6]] | BITSET[BOARDINDEX[file][7]] ;

			//===========================================================================
			//Initialize 8-bit diagonal mask
			//===========================================================================
			DIAGA8H1MASK[BOARDINDEX[file][rank]] = 0x0;
			if (diaga8h1 < 8)  // lower half, diagonals 0 to 7
			{
				for (square = 0 ; square <= diaga8h1 ; square ++)
				{
					DIAGA8H1MASK[BOARDINDEX[file][rank]] |= BITSET[BOARDINDEX[square][diaga8h1-square]];
				}
			}
			else  // upper half, diagonals 8 to 14
			{
				for (square = 0 ; square < 15 - diaga8h1 ; square ++)
				{
					DIAGA8H1MASK[BOARDINDEX[file][rank]] |= BITSET[BOARDINDEX[diaga8h1+square-7][7-square]];
				}
			}
			//===========================================================================
			//Initialize 8-bit diagonal mask, used in the movegenerator (see movegen.ccp)
			//===========================================================================
			DIAGA1H8MASK[BOARDINDEX[file][rank]] = 0x0;
			if (diaga1h8 > -1)  // lower half, diagonals 0 to 7
			{
				for (square = 0 ; square <= 7 - diaga1h8 ; square ++)
				{
					DIAGA1H8MASK[BOARDINDEX[file][rank]] |= BITSET[BOARDINDEX[diaga1h8 + square][square]];
				}
			}
			else
			{
				for (square = 0 ; square <= 7 + diaga1h8 ; square ++)
				{
					DIAGA1H8MASK[BOARDINDEX[file][rank]] |= BITSET[BOARDINDEX[square][square - diaga1h8]];
				}
			}
			
		}
	}
	
	//     ===========================================================================
	//     Now initialize the GEN_SLIDING_ATTACKS array, used to generate the sliding
	//     attack bitboards.
	//     unsigned char GEN_SLIDING_ATTACKS[8 squares][64 states] holds the attacks
	//     for any file, rank or diagonal - it is going to be usefull when generating the
	//     RANK_ATTACKS[64][64], FILE_ATTACKS[64][64], DIAGA8H1_ATTACKS[64][64] and
	//     DIAGA1H8_ATTACKS[64][64] arrays
	//     ===========================================================================
	
	// initialize CHARBITSET, this array is equivalant to BITSET for bitboards:
	// 8 chars, each with only 1 bit set.
	CHARBITSET[0] = 1;
	for (square = 1; square <= 7; square++) 
	{
		CHARBITSET[square] = CHARBITSET[square-1] << 1;
	}
	
	// loop over rank, file or diagonal squares:
	for (square = 0; square <= 7; square++)
	{
		// loop of occupancy states
		// state6Bit represents the 64 possible occupancy states of a rank,
		// except the 2 end-bits, because they don't matter for calculating attacks
		for (state6Bit = 0; state6Bit < 64; state6Bit++)      
		{
			state8Bit = state6Bit << 1; // create an 8-bit occupancy state
			attack8Bit = 0;
			if (square < 7)
			{
				attack8Bit |= CHARBITSET[square + 1];
			}
			slide = square + 2;
			while (slide <= 7) // slide in '+' direction
			{
				if ((~state8Bit) & (CHARBITSET[slide - 1]))
				{
					attack8Bit |= CHARBITSET[slide];
				}
				else break;
				slide++;
			}
			if (square > 0)
			{
				attack8Bit |= CHARBITSET[square - 1];
			}
			slide = square - 2;
			while (slide >= 0) // slide in '-' direction
			{
				if ((~state8Bit) & (CHARBITSET[slide + 1]))
				{
					attack8Bit |= CHARBITSET[slide];
				}
				else break;
				slide--;
			}
			GEN_SLIDING_ATTACKS[square][state6Bit] = attack8Bit;
		}
	}

	
	
	//     ===========================================================================
	//     Initialize all attack bitmaps, used in the movegenerator (see movegen.ccp)
	//     ===========================================================================
	
	for (square = 0; square < 64; square++)
	{
		KNIGHT_ATTACKS[square] = 0x0;
		KING_ATTACKS[square] = 0x0;
		WHITE_PAWN_ATTACKS[square] = 0x0;
		WHITE_PAWN_MOVES[square] = 0x0;
		WHITE_PAWN_DOUBLE_MOVES[square] = 0x0;
		BLACK_PAWN_ATTACKS[square] = 0x0;
		BLACK_PAWN_MOVES[square] = 0x0;
		BLACK_PAWN_DOUBLE_MOVES[square] = 0x0;  
		
		for (state = 0; state < 64; state++)
		{
			RANK_ATTACKS[square][state] = 0x0;
			FILE_ATTACKS[square][state] = 0x0;
			DIAGA8H1_ATTACKS[square][state] = 0x0;
			DIAGA1H8_ATTACKS[square][state] = 0x0;
		}
	}
 
	// WHITE_PAWN_ATTACKS
	for (square = 0; square < 64; square++)
	{
		file = FILES[square]; rank = RANKS[square];
		afile = file - 1; arank = rank + 1;
		if ((afile >= 0) & (afile <= 7) & (arank >= 0) & (arank <= 7))
			WHITE_PAWN_ATTACKS[square] |= BITSET[BOARDINDEX[afile][arank]];
		afile = file + 1; arank = rank + 1;
		if ((afile >= 0) & (afile <= 7) & (arank >= 0) & (arank <= 7))
			WHITE_PAWN_ATTACKS[square] |= BITSET[BOARDINDEX[afile][arank]];
	}
	
	// WHITE_PAWN_MOVES
	for (square = 0; square <64; square++)
	{
		file = FILES[square]; rank = RANKS[square];
		afile = file; arank = rank + 1;
		if ((afile >= 0) & (afile <= 7) & (arank >= 0) & (arank <= 7))
			WHITE_PAWN_MOVES[square] |= BITSET[BOARDINDEX[afile][arank]];
		if (rank == 1)
		{
			afile = file; arank = rank + 2;
			if ((afile >= 0) & (afile <= 7) & (arank >= 0) & (arank <= 7))
				WHITE_PAWN_DOUBLE_MOVES[square] |= BITSET[BOARDINDEX[afile][arank]];
		}
	}
	
	// BLACK_PAWN_ATTACKS
	for (square = 0; square < 64; square++)
	{
		file = FILES[square]; rank = RANKS[square];
		afile = file - 1; arank = rank - 1;
		if ((afile >= 0) & (afile <= 7) & (arank >= 0) & (arank <= 7))
			BLACK_PAWN_ATTACKS[square] |= BITSET[BOARDINDEX[afile][arank]];
		afile = file + 1; arank = rank - 1;
		if ((afile >= 0) & (afile <= 7) & (arank >= 0) & (arank <= 7))
			BLACK_PAWN_ATTACKS[square] |= BITSET[BOARDINDEX[afile][arank]];
	}
 
	// BLACK_PAWN_MOVES
	for (square = 0; square < 64; square++)
	{
		file = FILES[square]; rank = RANKS[square];
		afile = file; arank = rank - 1;
		if ((afile >= 0) & (afile <= 7) & (arank >= 0) & (arank <= 7))
			BLACK_PAWN_MOVES[square] |= BITSET[BOARDINDEX[afile][arank]];
		if (rank == 6)
		{
			afile = file; arank = rank - 2;
			if ((afile >= 0) & (afile <= 7) & (arank >= 0) & (arank <= 7))
				BLACK_PAWN_DOUBLE_MOVES[square] |= BITSET[BOARDINDEX[afile][arank]];
		}
	}
	
	// KNIGHT attacks;
	for (square = 0; square < 64; square++)
	{
		file = FILES[square];
		rank = RANKS[square];
		afile = file - 2; arank = rank + 1;
		if ((afile >= 0) & (afile <= 7) & (arank >= 0) & (arank <= 7))
			KNIGHT_ATTACKS[square] |= BITSET[BOARDINDEX[afile][arank]];
		afile = file - 1; arank = rank + 2;
		if ((afile >= 0) & (afile <= 7) & (arank >= 0) & (arank <= 7))
			KNIGHT_ATTACKS[square] |= BITSET[BOARDINDEX[afile][arank]];
		afile = file + 1; arank = rank + 2;
		if ((afile >= 0) & (afile <= 7) & (arank >= 0) & (arank <= 7))
			KNIGHT_ATTACKS[square] |= BITSET[BOARDINDEX[afile][arank]];
		afile = file + 2; arank = rank + 1;
		if ((afile >= 0) & (afile <= 7) & (arank >= 0) & (arank <= 7))
			KNIGHT_ATTACKS[square] |= BITSET[BOARDINDEX[afile][arank]];
		afile = file + 2; arank = rank - 1;
		if ((afile >= 0) & (afile <= 7) & (arank >= 0) & (arank <= 7))
			KNIGHT_ATTACKS[square] |= BITSET[BOARDINDEX[afile][arank]];
		afile = file + 1; arank = rank - 2;
		if ((afile >= 0) & (afile <= 7) & (arank >= 0) & (arank <= 7))
			KNIGHT_ATTACKS[square] |= BITSET[BOARDINDEX[afile][arank]];
		afile = file - 1; arank = rank - 2;
		if ((afile >= 0) & (afile <= 7) & (arank >= 0) & (arank <= 7))
			KNIGHT_ATTACKS[square] |= BITSET[BOARDINDEX[afile][arank]];
		afile = file - 2; arank = rank - 1;
		if ((afile >= 0) & (afile <= 7) & (arank >= 0) & (arank <= 7))
			KNIGHT_ATTACKS[square] |= BITSET[BOARDINDEX[afile][arank]];
	}
	
	// KING attacks;
	for (square = 0; square < 64; square++)
	{
		file = FILES[square]; rank = RANKS[square];
		afile = file - 1; arank = rank;
		if ((afile >= 0) & (afile <= 7) & (arank >= 0) & (arank <= 7))
			KING_ATTACKS[square] |= BITSET[BOARDINDEX[afile][arank]];
		afile = file - 1; arank = rank + 1;
		if ((afile >= 0) & (afile <= 7) & (arank >= 0) & (arank <= 7))
			KING_ATTACKS[square] |= BITSET[BOARDINDEX[afile][arank]];
		afile = file; arank = rank + 1;
		if ((afile >= 0) & (afile <= 7) & (arank >= 0) & (arank <= 7))
			KING_ATTACKS[square] |= BITSET[BOARDINDEX[afile][arank]];
		afile = file + 1; arank = rank + 1;
		if ((afile >= 0) & (afile <= 7) & (arank >= 0) & (arank <= 7))
			KING_ATTACKS[square] |= BITSET[BOARDINDEX[afile][arank]];
		afile = file + 1; arank = rank;
		if ((afile >= 0) & (afile <= 7) & (arank >= 0) & (arank <= 7))
			KING_ATTACKS[square] |= BITSET[BOARDINDEX[afile][arank]];
		afile = file + 1; arank = rank - 1;
		if ((afile >= 0) & (afile <= 7) & (arank >= 0) & (arank <= 7))
			KING_ATTACKS[square] |= BITSET[BOARDINDEX[afile][arank]];
		afile = file; arank = rank - 1;
		if ((afile >= 0) & (afile <= 7) & (arank >= 0) & (arank <= 7))
			KING_ATTACKS[square] |= BITSET[BOARDINDEX[afile][arank]];
		afile = file - 1; arank = rank - 1;
		if ((afile >= 0) & (afile <= 7) & (arank >= 0) & (arank <= 7))
			KING_ATTACKS[square] |= BITSET[BOARDINDEX[afile][arank]];
	}
 
	
	//  RANK attacks (ROOKS and QUEENS):
	//  use           unsigned char GEN_SLIDING_ATTACKS[8 squares] [64 states]
	//  to initialize BitMap        RANK_ATTACKS       [64 squares][64 states]
	//
	for (square = 0; square < 64; square++)
	{
		for (state6Bit = 0; state6Bit < 64; state6Bit++)
		{
			RANK_ATTACKS[square][state6Bit] = 0;
			RANK_ATTACKS[square][state6Bit] |=
				bitMap(GEN_SLIDING_ATTACKS[FILES[square]][state6Bit]) << (RANKSHIFT[square]-1);

		}
	}
	
	//  FILE attacks (ROOKS and QUEENS):
	//  use           unsigned char GEN_SLIDING_ATTACKS[8 squares] [64 states]
	//  to initialize BitMap        FILE_ATTACKS       [64 squares][64 states]
	//
	//  Occupancy transformation is as follows:
	//
	//   occupancy state bits of the file:               occupancy state bits in GEN_SLIDING_ATTACKS:
	//
	//        . . . . . . . . MSB                           LSB         MSB
	//        . . . . . A . .                    =>         A B C D E F . .      
	//        . . . . . B . .
	//        . . . . . C . .
	//        . . . . . D . .
	//        . . . . . E . .
	//        . . . . . F . .
	//    LSB . . . . . . . .
	//
	//  The reverse transformation is as follows:
	//
	//   attack bits in GEN_SLIDING_ATTACKS:             attack bits in the file:
	//
	//        LSB         MSB                               . . . . . m . . MSB
	//        m n o p q r s t                    =>         . . . . . n . .
	//                                                      . . . . . o . .
	//                                                      . . . . . p . .
	//                                                      . . . . . q . .
	//                                                      . . . . . r . .
	//                                                      . . . . . s . .
	//                                                 LSB  . . . . . t . .
	//
	for (square = 0; square < 64; square++)
	{
		for (state6Bit = 0; state6Bit < 64; state6Bit++)
		{
			FILE_ATTACKS[square][state6Bit] = 0x0;
			
			// check to see if attackbit'-th  bit is set in GEN_SLIDING_ATTACKS, for this combination of square/occupancy state
			for (attackbit = 0; attackbit < 8; attackbit++) // from LSB to MSB
			{
				//  conversion from 64 board squares to the 8 corresponding positions in the GEN_SLIDING_ATTACKS array: "8-RANKS[square]"
				if (GEN_SLIDING_ATTACKS[7-RANKS[square]][state6Bit] & CHARBITSET[attackbit])
				{
					// the bit is set, so we need to update FILE_ATTACKS accordingly:
					// conversion of square/attackbit to the corresponding 64 board FILE: FILES[square]
					// conversion of square/attackbit to the corresponding 64 board RANK: 8-attackbit
					file = FILES[square];
					rank = 7 - attackbit;
					FILE_ATTACKS[square][state6Bit] |=  BITSET[BOARDINDEX[file][rank]];
				}
			}
		}
	}
	
	//  DIAGA8H1_ATTACKS attacks (BISHOPS and QUEENS):
	for (square = 0; square < 64; square++)
	{
		for (state6Bit = 0; state6Bit < 64; state6Bit++)
		{
			DIAGA8H1_ATTACKS[square][state6Bit] = 0x0;
			for (attackbit = 0; attackbit < 8; attackbit++) // from LSB to MSB
			{
				//  conversion from 64 board squares to the 8 corresponding positions in the GEN_SLIDING_ATTACKS array: MIN((8-RANKS[square]),(FILES[square]-1))
				if (GEN_SLIDING_ATTACKS[(7-RANKS[square]) < (FILES[square]) ? (7-RANKS[square]) : (FILES[square])][state6Bit] & CHARBITSET[attackbit])
				{
					// the bit is set, so we need to update FILE_ATTACKS accordingly:
					// conversion of square/attackbit to the corresponding 64 board file and rank:
					diaga8h1 = FILES[square] + RANKS[square]; // from 0 to 14, longest diagonal = 7
					if (diaga8h1 < 8)
					{
						file = attackbit;
						rank = diaga8h1 - file;
					}
					else
					{
						rank = 7 - attackbit;
						file = diaga8h1 - rank;
					}
					if ((file >= 0) && (file < 8) && (rank >= 0) && (rank < 8))
					{
						DIAGA8H1_ATTACKS[square][state6Bit] |=  BITSET[BOARDINDEX[file][rank]];
					}
				}
			}
		}
	}
	
	
	
	
	//  DIAGA1H8_ATTACKS attacks (BISHOPS and QUEENS):
	for (square = 0; square < 64; square++)
	{
		for (state6Bit = 0; state6Bit < 64; state6Bit++)
		{
			DIAGA1H8_ATTACKS[square][state6Bit] = 0x0;
			for (attackbit = 0; attackbit < 8; attackbit++) // from LSB to MSB
			{
				//  conversion from 64 board squares to the 8 corresponding positions in the GEN_SLIDING_ATTACKS array: MIN((8-RANKS[square]),(FILES[square]-1))
				if (GEN_SLIDING_ATTACKS[(RANKS[square]) < (FILES[square]) ? (RANKS[square]) : (FILES[square])][state6Bit] & CHARBITSET[attackbit])
				{
					// the bit is set, so we need to update FILE_ATTACKS accordingly:
					// conversion of square/attackbit to the corresponding 64 board file and rank:
					diaga1h8 = FILES[square] - RANKS[square]; // from -7 to 7, longest diagonal = 0
					if (diaga1h8 < 0)
					{
						file = attackbit;
						rank = file - diaga1h8;
					}
					else
					{
						rank = attackbit ;
						file = diaga1h8 + rank;
					}
					if ((file >= 0) && (file < 8) && (rank >= 0) && (rank < 8))
					{
						DIAGA1H8_ATTACKS[square][state6Bit] |=  BITSET[BOARDINDEX[file][rank]];
					}
				}
			}
		}
	}

	MASKBD[0]=BITSET[B1] |BITSET[C1]| BITSET[D1];
	MASKBD[1]=BITSET[B8] |BITSET[C8]| BITSET[D8];
	MASKCE[0]=BITSET[C1] |BITSET[D1]| BITSET[E1];
	MASKCE[1]=BITSET[C8] |BITSET[D8]| BITSET[E8];
	MASKFG[0]=BITSET[F1] |BITSET[G1];
	MASKFG[1]=BITSET[F8] |BITSET[G8];
	MASKEG[0]=BITSET[E1] |BITSET[F1]| BITSET[G1];
	MASKEG[1]=BITSET[E8] |BITSET[F8]| BITSET[G8];

	for(square=0;square<64;square++){
		bitMap occupiedSquares=BITSET[square];
		KINGRAYS[square]=RANKATTACKS(square);
		KINGRAYS[square]|=FILEATTACKS(square);
		KINGRAYS[square]|=SLIDEA8H1ATTACKS(square);
		KINGRAYS[square]|=SLIDEA1H8ATTACKS(square);
		KINGRAYS[square]|=KNIGHT_ATTACKS[square];
		KINGRAYS[square]|=BITSET[square];

		//displayBitmap(KINGRAYS[square]);
	}

	for(square=0;square<64;square++){
		ISOLATED_PAWN[square]=0;
		int file= FILES[square];

		if(file>0){
			for(int rank=0;rank<8;rank++){
				ISOLATED_PAWN[square]|=BITSET[BOARDINDEX[file-1][rank]];
			}
		}
		if(file<7){
			for(int rank=0;rank<8;rank++){
				ISOLATED_PAWN[square]|=BITSET[BOARDINDEX[file+1][rank]];
			}
		}
	}
	for(square=0;square<64;square++){
		PASSED_PAWN[0][square]=0;
		PASSED_PAWN[1][square]=0;
		SQUARES_IN_FRONT_OF[0][square]=0;
		SQUARES_IN_FRONT_OF[1][square]=0;
		int file= FILES[square];
		int rank= RANKS[square];

		for(int i=rank+1;i<8;i++){
			if(file>0){
				PASSED_PAWN[0][square] |= BITSET[BOARDINDEX[file-1][i]];
			}
			PASSED_PAWN[0][square] |= BITSET[BOARDINDEX[file][i]];
			SQUARES_IN_FRONT_OF[0][square] |= BITSET[BOARDINDEX[file][i]];
			if(file<7){
				PASSED_PAWN[0][square] |= BITSET[BOARDINDEX[file+1][i]];
			}
		}

		for(int i=rank-1;i>=0;i--){
			if(file>0){
				PASSED_PAWN[1][square] |= BITSET[BOARDINDEX[file-1][i]];
			}
			PASSED_PAWN[1][square] |= BITSET[BOARDINDEX[file][i]];
			SQUARES_IN_FRONT_OF[1][square] |= BITSET[BOARDINDEX[file][i]];
			if(file<7){
				PASSED_PAWN[1][square] |= BITSET[BOARDINDEX[file+1][i]];
			}
		}
	}

	for(square=0;square<64;square++){
		PAWNKINGSHIELD[0][0][square]=0;
		PAWNKINGSHIELD[0][1][square]=0;
		PAWNKINGSHIELD[1][0][square]=0;
		PAWNKINGSHIELD[1][1][square]=0;
		KINGSHIELD[0][square]=0;
		KINGSHIELD[0][square]=0;

		
		//int file= FILES[square];
		int rank= RANKS[square];

		if(rank<7){
			KINGSHIELD[0][square]|=PASSED_PAWN[0][square] & RANKMASK[square+8];
			PAWNKINGSHIELD[0][0][square]|=PASSED_PAWN[0][square] & RANKMASK[square+8];
		}
		if(rank<6){
			PAWNKINGSHIELD[1][0][square]|=PASSED_PAWN[0][square] & RANKMASK[square+16];
			KINGSHIELD[0][square]|=PASSED_PAWN[0][square] & RANKMASK[square+16];
		}
		KINGSHIELD[0][square]|=ISOLATED_PAWN[square] & RANKMASK[square];
		if(rank>0){
			KINGSHIELD[0][square]|=PASSED_PAWN[1][square] & RANKMASK[square-8];
		}

		


		if(rank>0){
			KINGSHIELD[1][square]|=PASSED_PAWN[1][square] & RANKMASK[square-8];
			PAWNKINGSHIELD[0][1][square]|=PASSED_PAWN[1][square] & RANKMASK[square-8];
		}
		if(rank>1){
			KINGSHIELD[1][square]|=PASSED_PAWN[1][square] & RANKMASK[square-16];
			PAWNKINGSHIELD[1][1][square]|=PASSED_PAWN[1][square] & RANKMASK[square-16];
		}
		KINGSHIELD[1][square]|=ISOLATED_PAWN[square] & RANKMASK[square];
		if(rank<7){
			KINGSHIELD[1][square]|=PASSED_PAWN[0][square] & RANKMASK[square+8];
		}
		
	}

	

	SQUARE_COLOR_BITMAP[0]=0;
	for(square=0;square<64;square++){
		if(SQUARE_COLOR[square]==0){
			SQUARE_COLOR_BITMAP[0] |=BITSET[square];
		}
	}
	SQUARE_COLOR_BITMAP[1]=~SQUARE_COLOR_BITMAP[0];

	for(square=0;square<64;square++){
		for(int i=0;i<64;i++){
			squareDistance[i][square] =std::max( abs( FILES[i] - FILES[square] ) , abs( RANKS[i] - RANKS[square] ));
		}
	}

	for(square=0;square<64;square++){
		for(int i=0;i<64;i++){
			SQUARES_BETWEEN[square][i]=0;
			SQUARES_BETWEEN_DIRECTION[square][i]=NULL;
		}
	}
	for(square=0;square<64;square++){
		for(int i=0;i<64;i++){
			if(square==i){
				SQUARES_BETWEEN[square][i]=0;
			}
			if(FILES[square]==FILES[i]){/// stessa colonna
				SQUARES_BETWEEN_DIRECTION[square][i]=&FILEMASK[square];
				if(RANKS[i]>RANKS[square]){ // in salita
					int temp=RANKS[square]+1;
					while(temp<RANKS[i]){
						SQUARES_BETWEEN[square][i]|=BITSET[BOARDINDEX[FILES[square]][temp]];
						temp++;
					}
					//displayBitmap(BITSET[square]);
					//displayBitmap(BITSET[i]);
					//displayBitmap(SQUARES_BETWEEN[square][i]);
					//getch();
				}
				if(RANKS[i]<RANKS[square]){ // in discesa
					int temp=RANKS[square]-1;
					while(temp>RANKS[i]){
						SQUARES_BETWEEN[square][i]|=BITSET[BOARDINDEX[FILES[square]][temp]];
						temp--;
					}
					//displayBitmap(BITSET[square]);
					//displayBitmap(BITSET[i]);
					//displayBitmap(SQUARES_BETWEEN[square][i]);
					//getch();
				}
			}
			if(RANKS[square]==RANKS[i]){/// stessa riga
				SQUARES_BETWEEN_DIRECTION[square][i]=&RANKMASK[square];
				if(FILES[i]>FILES[square]){ // in salita
					int temp=FILES[square]+1;
					while(temp<FILES[i]){
						SQUARES_BETWEEN[square][i]|=BITSET[BOARDINDEX[temp][RANKS[square]]];
						temp++;
					}
					//displayBitmap(BITSET[square]);
					//displayBitmap(BITSET[i]);
					//displayBitmap(SQUARES_BETWEEN[square][i]);
					//getch();
				}
				if(FILES[i]<FILES[square]){ // in discesa
					int temp=FILES[square]-1;
					while(temp>FILES[i]){
						SQUARES_BETWEEN[square][i]|=BITSET[BOARDINDEX[temp][RANKS[square]]];
						temp--;
					}
					//displayBitmap(BITSET[square]);
					//displayBitmap(BITSET[i]);
					//displayBitmap(SQUARES_BETWEEN[square][i]);
					//getch();
				}
			}
			if(DIAGA1H8MASK[square]& BITSET[i]){
				SQUARES_BETWEEN_DIRECTION[square][i]=&DIAGA1H8MASK[square];
				if(FILES[i]>FILES[square]){ // in salita
					int temp=FILES[square]+1;
					int temp2=RANKS[square]+1;
					while(temp<FILES[i]){
						SQUARES_BETWEEN[square][i]|=BITSET[BOARDINDEX[temp][temp2]];
						temp++;
						temp2++;
					}
					//displayBitmap(BITSET[square]);
					//displayBitmap(BITSET[i]);
					//displayBitmap(SQUARES_BETWEEN[square][i]);
					//getch();
				}
				if(FILES[i]<FILES[square]){ // in discesa
					int temp=FILES[square]-1;
					int temp2=RANKS[square]-1;
					while(temp>FILES[i]){
						SQUARES_BETWEEN[square][i]|=BITSET[BOARDINDEX[temp][temp2]];
						temp--;
						temp2--;
					}
					//displayBitmap(BITSET[square]);
					//displayBitmap(BITSET[i]);
					//displayBitmap(SQUARES_BETWEEN[square][i]);
					//getch();
				}
			}

			if(DIAGA8H1MASK[square]& BITSET[i]){
				SQUARES_BETWEEN_DIRECTION[square][i]=&DIAGA8H1MASK[square];
				if(FILES[i]>FILES[square]){ // in salita
					int temp=FILES[square]+1;
					int temp2=RANKS[square]-1;
					while(temp<FILES[i]){
						SQUARES_BETWEEN[square][i]|=BITSET[BOARDINDEX[temp][temp2]];
						temp++;
						temp2--;
					}
					//displayBitmap(BITSET[square]);
					//displayBitmap(BITSET[i]);
					//displayBitmap(SQUARES_BETWEEN[square][i]);
					//getch();
				}
				if(FILES[i]<FILES[square]){ // in discesa
					int temp=FILES[square]-1;
					int temp2=RANKS[square]+1;
					while(temp>FILES[i]){
						SQUARES_BETWEEN[square][i]|=BITSET[BOARDINDEX[temp][temp2]];
						temp--;
						temp2++;
					}
					//displayBitmap(BITSET[square]);
					//displayBitmap(BITSET[i]);
					//displayBitmap(SQUARES_BETWEEN[square][i]);
					//getch();
				}
			}


		}
	}



}
